﻿using ConfExpert.Properties;
using DevExpress.XtraEditors;
using DevTeam;
using Microsoft.Win32;
using System;
using System.Data;
using System.Drawing;
using System.IO;
using WIA;


namespace ConfExpert.Utility.Peripheral
{
    public class Scanner
    {
        static Device device;
        static string DeviceId = string.Empty;
        static IItem PreparedScanner;

        //çalışması için http://www.microsoft.com/downloads/en/details.aspx?familyid=a332a77a-01b8-4de6-91c2-b7ea32537e29&displaylang=en 
        //adresinden indirilecek paketle, regsvr32 wiaaut.DLL demek gerekiyor! 

        private static void Initialize(int dotsperinch = 300)
        {
            try
            {
                RegistryKey register = Registry.CurrentUser.CreateSubKey(@"Software\ConfExpert");
                DeviceId = (string)register.GetValue("DeviceID", String.Empty);
                if (DeviceId == string.Empty)
                    DeviceId = AppSession.ScannerDeviceId;

                if (DeviceId == string.Empty)
                    OpenDeviceDialog();

                DeviceManager manager = new DeviceManager();
                device = null;
                foreach (DeviceInfo info in manager.DeviceInfos)
                {
                    if (info.DeviceID == DeviceId)
                    {
                        device = info.Connect();
                        break;
                    }
                }

                WIA.Device scanner = null;
                try
                {
                    object something = 1;
                    scanner = manager.DeviceInfos.get_Item(ref something).Connect();
                }
                catch (Exception ex)
                {
                    throw ex;
                }

                int DPI = dotsperinch;




                PreparedScanner = scanner.Items[1];

                SetProperty(PreparedScanner, "6146", 1);    //Color: 4 black and white, 2 grayscale, 1 color, 0 unspecified
                SetProperty(PreparedScanner, "6147", DPI);  //Horizontal Resolution
                SetProperty(PreparedScanner, "6148", DPI);  //Vertical Resolution            
                SetProperty(PreparedScanner, "6149", 16);   //Horizontal Starting Position (Scanning Area)
                SetProperty(PreparedScanner, "6150", 0);    //Vertical Starting Position (Scanning Area)

                // SetProperty(PreparedScanner, "6154", 0);    //Brightness
                // SetProperty(PreparedScanner, "6155", 0);    //Contrast

                //SetProperty(PreparedScanner, "4104", 16);     //Color Depth
                //SetProperty(PreparedScanner, "71723", 1);     //Color Enhanced

                /*
                string s = string.Empty;
                foreach (Property propertyItem in Item1.Properties)
                    if (!propertyItem.IsReadOnly)
                        s += String.Format("{0}\t{1}\t{2}", propertyItem.Name, propertyItem.PropertyID, propertyItem.get_Value()) + Environment.NewLine;
                */

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static void OpenDeviceDialog()
        {
            CommonDialog dialog = new CommonDialog();
            device = dialog.ShowSelectDevice(WiaDeviceType.ScannerDeviceType, true, false);
            if (device != null)
            {
                RegistryKey register = Registry.CurrentUser.CreateSubKey(@"Software\ConfExpert");
                register.SetValue("DeviceID", DeviceId, RegistryValueKind.String);
                AppSession.ScannerDeviceId = DeviceId;
                Registry.LocalMachine.Flush();
                DeviceId = device.DeviceID;
            }
        }

        static void SetProperty(IItem item, object property, object value)
        {
            WIA.Property aProperty = item.Properties.get_Item(ref property);
            aProperty.set_Value(ref value);
        }

        static object GetProperty(IItem item, object property)
        {
            WIA.Property aProperty = item.Properties.get_Item(ref property);
            return aProperty.get_Value();
        }


        public class PhotosTable
        {
            public DataTable Table = new DataTable();

            public DataRow AddRow(int productId, Image scanned, bool big = false)
            {
                int ProductId;
                byte[] Photo = null;
                byte[] Photo1;
                byte[] Photo2;
                byte[] Photo3;
                byte[] Photo4;
                byte[] Photo1fs = null;
                byte[] Photo500;
                string Tip = (big ? "big" : string.Empty);

                //2014-03-04 tarihinden itibaren kullanılmaya başlandı.
                ProductId = productId; //Önemsiz
                if (Temp < 1)
                    Photo = scanned.ToPNG();

                Bitmap mask = Resources.Mask;

                Photo1 = scanned
                            .CropFromCenter(224)
                            .Resize(28)
                            .Unsharpen()
                            .ToJPEG();

                Photo2 = scanned
                            .CropFromCenter(432)
                            .Resize(72)
                            .Unsharpen()
                            .ToJPEG();

                Photo3 = scanned
                            .CropFromCenter(474)
                            .Resize(150)
                            .Unsharpen()
                            .ToJPEG();

                Photo4 = scanned
                             .CropFromCenter(1140)
                             .Resize(400)
                             .Mask(mask)
                             .Unsharpen()
                             .ToJPEG();

                if (big)
                    if (Temp < 1)
                        Photo1fs = scanned
                                 .CropFromCenter(2280)
                                 .Resize(800)
                                 .Unsharpen()
                                 .ToJPEG();

                Photo500 = scanned
                             .CropFromCenter(1140)
                             .Resize(500)
                             .Unsharpen()
                             .ToJPEG();

                DataRow dr = Table.Rows.Find(ProductId);
                object oPhoto1fs;
                if (Photo1fs == null)
                    oPhoto1fs = DBNull.Value;

                if (dr == null)
                    dr = Table.Rows.Add(ProductId, Photo, Photo1, Photo2, Photo3, Photo4, Photo1fs, Photo500, Tip);
                else
                {
                    dr["Photo"] = Photo;
                    dr["Photo1"] = Photo1;
                    dr["Photo2"] = Photo2;
                    dr["Photo3"] = Photo3;
                    dr["Photo4"] = Photo4;
                    dr["Photo1fs"] = Photo1fs;
                    dr["Photo500"] = Photo500;
                    dr["Tip"] = Tip;
                }

                return dr;
            }

            public DataRow AddFaturaRow(string faturano, Image scanned)
            {
                byte[] Photo = scanned
                            .ResizeA4(1200)
                            .Unsharpen()
                            .ToPNG();

                DataRow dr = Table.NewRow();
                dr["ProductId"]= 0;
                dr["Photo"] = Photo;
                dr["Tip"] = faturano;
                Table.Rows.Add(dr);

                return dr;
            }

            public PhotosTable()
            {
                Table.Columns.Add("ProductId", typeof(int));
                Table.PrimaryKey = new DataColumn[] { Table.Columns["ProductId"] };

                Table.Columns.Add("Photo", typeof(byte[]));
                Table.Columns.Add("Photo1", typeof(byte[]));
                Table.Columns.Add("Photo2", typeof(byte[]));
                Table.Columns.Add("Photo3", typeof(byte[]));
                Table.Columns.Add("Photo4", typeof(byte[]));
                Table.Columns.Add("Photo1fs", typeof(byte[]));
                Table.Columns.Add("Photo500", typeof(byte[]));
                Table.Columns.Add("Tip", typeof(string));
            }

            int Temp = 0;
            public PhotosTable(string dummy)
                :this(true)
            {
                this.Temp = 1;
            }

            public PhotosTable(bool FeatureFields)
                :this()
            {
                for (int i = 0; i < 47; i++)
                    Table.Columns.Add(string.Format("F{0:00}", i), typeof(decimal));
            }

            public Image GetPhoto500()
            {
                return ConvertByteArrayToImage(Table.Rows[0]["Photo500"] as byte[]);
            }
         
            Image ConvertByteArrayToImage(byte[] byteArray)
            {
                try
                {
                    if (byteArray != null)
                    {
                        MemoryStream ms = new MemoryStream(byteArray, 0, byteArray.Length);
                        ms.Write(byteArray, 0, byteArray.Length);
                        return Image.FromStream(ms, true);
                    }
                }
                catch (Exception) { return null; }
                return null;
            }
        }

        public class PhotosRTable
        {
            public DataTable Table = new DataTable();

            public DataRow AddRow(int rollId, Image scanned, bool big = false)
            {
                int RollId;
                byte[] Photo;
                byte[] Photo1;
                byte[] Photo2;
                byte[] Photo3;
                byte[] Photo4;
                byte[] Photo1fs = null;
                byte[] Photo500;
                string Tip = (big ? "big" : string.Empty);

                //2014-03-04 tarihinden itibaren kullanılmaya başlandı.
                RollId = rollId; //Önemsiz
                Photo = scanned.ToPNG();

                Bitmap mask = Resources.Mask;

                Photo1 = scanned
                            .CropFromCenter(224)
                            .Resize(28)
                            .Unsharpen()
                            .ToJPEG();

                Photo2 = scanned
                            .CropFromCenter(432)
                            .Resize(72)
                            .Unsharpen()
                            .ToJPEG();

                Photo3 = scanned
                            .CropFromCenter(474)
                            .Resize(150)
                            .Unsharpen()
                            .ToJPEG();

                Photo4 = scanned
                             .CropFromCenter(1140)
                             .Resize(400)
                             .Mask(mask)
                             .Unsharpen()
                             .ToJPEG();

                if (big)
                    Photo1fs = scanned
                                 .CropFromCenter(2280)
                                 .Resize(800)
                                 .Unsharpen()
                                 .ToJPEG();

                Photo500 = scanned
                             .CropFromCenter(1140)
                             .Resize(500)
                             .Unsharpen()
                             .ToJPEG();

                DataRow dr = Table.Rows.Find(RollId);
                object oPhoto1fs;
                if (Photo1fs == null)
                    oPhoto1fs = DBNull.Value;

                if (dr == null)
                    dr = Table.Rows.Add(rollId, Photo, Photo1, Photo2, Photo3, Photo4, Photo1fs, Photo500, Tip);
                else
                {
                    dr["Photo"] = Photo;
                    dr["Photo1"] = Photo1;
                    dr["Photo2"] = Photo2;
                    dr["Photo3"] = Photo3;
                    dr["Photo4"] = Photo4;
                    dr["Photo1fs"] = Photo1fs;
                    dr["Photo500"] = Photo500;
                    dr["Tip"] = Tip;
                }

                return dr;
            }

            public PhotosRTable()
            {
                Table.Columns.Add("RollId", typeof(int));
                Table.PrimaryKey = new DataColumn[] { Table.Columns["RollId"] };

                Table.Columns.Add("Photo", typeof(byte[]));
                Table.Columns.Add("Photo1", typeof(byte[]));
                Table.Columns.Add("Photo2", typeof(byte[]));
                Table.Columns.Add("Photo3", typeof(byte[]));
                Table.Columns.Add("Photo4", typeof(byte[]));
                Table.Columns.Add("Photo1fs", typeof(byte[]));
                Table.Columns.Add("Photo500", typeof(byte[]));
                Table.Columns.Add("Tip", typeof(string));
            }
        }

        public static Image Scan(bool big = false)
        {
            try
            {
                Initialize();

                double ScanningArea = big ? 2400 : 1200;

                SetProperty(PreparedScanner, "6151", ScanningArea);  //Horizontal Scanning Area
                SetProperty(PreparedScanner, "6152", ScanningArea);  //Vertical Scanning Area

                WIA.ImageFile ImageX = (WIA.ImageFile)PreparedScanner.Transfer(WIA.FormatID.wiaFormatPNG);
                Vector vector = ImageX.FileData;
                return Image.FromStream(new MemoryStream((byte[])vector.get_BinaryData()));
            }
            catch (Exception Ex)
            {
                XtraMessageBox.Show("Tarayıcıya ulaşılamıyor. Cihazın açık ve kablolarının takılı olduğundan emin olun.", "Hata!", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
                throw Ex;
            }
        }

        /*public static Image ScanTemp()
        {
            try
            {
                Initialize();

                double ScanningArea = 1200;

                SetProperty(PreparedScanner, "6151", ScanningArea);  //Horizontal Scanning Area
                SetProperty(PreparedScanner, "6152", ScanningArea);  //Vertical Scanning Area

                WIA.ImageFile ImageX = (WIA.ImageFile)PreparedScanner.Transfer(WIA.FormatID.wiaFormatPNG);
                Vector vector = ImageX.FileData;
                return Image.FromStream(new MemoryStream((byte[])vector.get_BinaryData()));
            }
            catch (Exception Ex)
            {
                XtraMessageBox.Show("Tarayıcıya ulaşılamıyor. Cihazın açık ve kablolarının takılı olduğundan emin olun.", "Hata!", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
                throw Ex;
            }
        }*/

        public static Image ScanA4()
        {
            try
            {
                Initialize();

                //double ScanningArea = 1200;

                //SetProperty(PreparedScanner, "6151", ScanningArea);  //Horizontal Scanning Area
                //SetProperty(PreparedScanner, "6152", ScanningArea);  //Vertical Scanning Area

                WIA.ImageFile ImageX = (WIA.ImageFile)PreparedScanner.Transfer(WIA.FormatID.wiaFormatPNG);
                Vector vector = ImageX.FileData;
                return Image.FromStream(new MemoryStream((byte[])vector.get_BinaryData()));
            }
            catch (Exception Ex)
            {
                XtraMessageBox.Show("Tarayıcıya ulaşılamıyor. Cihazın açık ve kablolarının takılı olduğundan emin olun.", "Hata!", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
                throw Ex;
            }
        }

        public static Image ScanDoc()
        {
            try
            {
                Initialize();
                /*
                SetProperty(PreparedScanner, "6151", 2400);  //Horizontal Scanning Area
                SetProperty(PreparedScanner, "6152", 3100);  //Vertical Scanning Area
                */
                WIA.ImageFile ImageX = (WIA.ImageFile)PreparedScanner.Transfer(WIA.FormatID.wiaFormatPNG);
                Vector vector = ImageX.FileData;
                return Image.FromStream(new MemoryStream((byte[])vector.get_BinaryData()));
            }
            catch (Exception Ex)
            {
                XtraMessageBox.Show("Tarayıcıya ulaşılamıyor. Cihazın açık ve kablolarının takılı olduğundan emin olun.", "Hata!", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
                throw Ex;
            }
        }

        public static Image Scan600(int Height)
        {
            try
            {
                Initialize(300);

                double ScanningArea = 2400;

                SetProperty(PreparedScanner, "6151", ScanningArea);  //Horizontal Scanning Area
                SetProperty(PreparedScanner, "6152", 120 * Height /*ScanningArea*/);  //Vertical Scanning Area

                WIA.ImageFile ImageX = (WIA.ImageFile)PreparedScanner.Transfer(WIA.FormatID.wiaFormatPNG);
                Vector vector = ImageX.FileData;
                return Image.FromStream(new MemoryStream((byte[])vector.get_BinaryData()));
            }
            catch (Exception Ex)
            {
                XtraMessageBox.Show("Tarayıcıya ulaşılamıyor. Cihazın açık ve kablolarının takılı olduğundan emin olun.", "Hata!");
                throw Ex;
            }
        }

        public class PageTable
        {
            public DataTable Table = new DataTable();

            public DataRow AddRow(string DosyaNo, Image scanned, int sayfa = 1)
            {
                //byte[] Photo = scanned.ToPNG();
                byte[] Photo1;
                scanned = scanned
                    //.Resize(32) //BUNU DEĞİŞTİR!
                    .Unsharpen();

                if (sayfa > 1)
                    scanned.RotateFlip(RotateFlipType.Rotate90FlipNone);

                Photo1 = scanned
                    .ToJPEG();  //BELKİ BUNU DA!

                DataRow dr = Table.Rows.Find(DosyaNo);

                if (dr == null)
                {
                    DataRow x = Table.NewRow();
                    x["DosyaNo"] = DosyaNo;

                    Table.Rows.Add(x);

                    dr = Table.Rows.Find(DosyaNo);
                }

                dr["S" + sayfa] = Photo1;

                return dr;
            }

            public PageTable()
            {
                Table.Columns.Add("DosyaNo", typeof(string));
                Table.PrimaryKey = new DataColumn[] { Table.Columns["DosyaNo"] };

                Table.Columns.Add("S1", typeof(byte[]));
                Table.Columns.Add("S2", typeof(byte[]));
                Table.Columns.Add("S3", typeof(byte[]));
                Table.Columns.Add("S4", typeof(byte[]));
                Table.Columns.Add("S5", typeof(byte[]));
            }
        }

        public static Image ScanPage()
        {
            try
            {
                Initialize();

                int DPI = 150;

                SetProperty(PreparedScanner, "6147", DPI);  //Horizontal Resolution
                SetProperty(PreparedScanner, "6148", DPI);  //Vertical Resolution            

                //SetProperty(PreparedScanner, "6151", 1200);  //Horizontal Extent (Scanning Area)
                //SetProperty(PreparedScanner, "6152", 2400);  //Vertical Scanning Area
                SetProperty(PreparedScanner, "6149", 10);   //Horizontal Starting Position (Scanning Area)
                SetProperty(PreparedScanner, "6150", 10);    //Vertical Starting Position (Scanning Area)
                //object orientation = GetProperty(PreparedScanner, "6156");
                //SetProperty(PreparedScanner, "6156", (portrait ? WIA_IPS_ORIENTATION.WIA_PORTRAIT : WIA_IPS_ORIENTATION.WIA_LANDSCAPE)	/* WIA_PROP_LIST*/);
                /*
  WIA_DPS_ORIENTATION and WIA_DPS_ROTATION constants 
  WIA_PORTRAIT = 0; 
  WIA_LANSCAPE = 1; 
  WIA_ROT180 = 2; 
  WIA_ROT270 = 3; */

                WIA.ImageFile ImageX = (WIA.ImageFile)PreparedScanner.Transfer(WIA.FormatID.wiaFormatPNG);
                Vector vector = ImageX.FileData;
                return Image.FromStream(new MemoryStream((byte[])vector.get_BinaryData()));
            }
            catch (Exception Ex)
            {
                XtraMessageBox.Show("Tarayıcıya ulaşılamıyor. Cihazın açık ve kablolarının takılı olduğundan emin olun.", "Hata!");
                throw Ex;
            }
        }
    }
}

/*
 * 
 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms630202(v=vs.85).aspx
 * 
WIA Property Constant Definitions

const DeviceID = 2
const Manufacturer = 3
const Description = 4
const Type = 5
const Port = 6
const Name = 7
const Server = 8
const RemoteDevID = 9
const UIClassID = 10
const FirmwareVersion = 1026
const ConnectStatus = 1027
const DeviceTime = 1028
const PicturesTaken = 2050
const PicturesRemaining = 2051
const ExposureMode = 2052
const ExposureCompensation = 2053
const ExposureTime = 2054
const FNumber = 2055
const FlashMode = 2056
const FocusMode = 2057
const FocusManualDist = 2058
const ZoomPosition = 2059
const PanPosition = 2060
const TiltPostion = 2061
const TimerMode = 2062
const TimerValue = 2063
const PowerMode = 2064
const BatteryStatus = 2065
const Dimension = 2070
const HorizontalBedSize = 3074
const VerticalBedSize = 3075
const HorizontalSheetFeedSize = 3076
const VerticalSheetFeedSize = 3077
const SheetFeederRegistration = 3078
const HorizontalBedRegistration = 3079
const VerticalBedRegistraion = 3080
const PlatenColor = 3081
const PadColor = 3082
const FilterSelect = 3083
const DitherSelect = 3084
const DitherPatternData = 3085
const DocumentHandlingCapabilities = 3086
const DocumentHandlingStatus = 3087
const DocumentHandlingSelect = 3088
const DocumentHandlingCapacity = 3089
const HorizontalOpticalResolution = 3090
const VerticalOpticalResolution = 3091
const EndorserCharacters = 3092
const EndorserString = 3093
const ScanAheadPages = 3094
const MaxScanTime = 3095
const Pages = 3096
const PageSize = 3097
const PageWidth = 3098
const PageHeight = 3099
const Preview = 3100
const TransparencyAdapter = 3101
const TransparecnyAdapterSelect = 3102
const ItemName = 4098
const FullItemName = 4099
const ItemTimeStamp = 4100
const ItemFlags = 4101
const AccessRights = 4102
const DataType = 4103
const BitsPerPixel = 4104
const PreferredFormat = 4105
const Format = 4106
const Compression = 4107
const MediaType = 4108
const ChannelsPerPixel = 4109
const BitsPerChannel = 4110
const Planar = 4111
const PixelsPerLine = 4112
const BytesPerLine = 4113
const NumberOfLines = 4114
const GammaCurves = 4115
const ItemSize = 4116
const ColorProfiles = 4117
const BufferSize = 4118
const RegionType = 4119
const ColorProfileName = 4120
const ApplicationAppliesColorMapping = 4121
const StreamCompatibilityID = 4122
const ThumbData = 5122
const ThumbWidth = 5123
const ThumbHeight = 5124
const AudioAvailable = 5125
const AudioFormat = 5126
const AudioData = 5127
const PicturesPerRow = 5128
const SequenceNumber = 5129
const TimeDelay = 5130
const CurrentIntent = 6146
const HorizontalResolution = 6147
const VerticalResolution = 6148
const HorizontalStartPostion = 6149
const VerticalStartPosition = 6150
const HorizontalExtent = 6151
const VerticalExtent = 6152
const PhotometricInterpretation = 6153
const Brightness = 6154
const Contrast = 6155
const Orientation = 6156
const Rotation = 6157
const Mirror = 6158
const Threshold = 6159
const Invert= 6160
const LampWarmUpTime = 6161 
*/